package com.mojo.concurrent.concurrent_05_util;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

/**
 * countdownLatch工具类示例
 * <p>
 * 场景：等待N个子线程执行完毕
 * </p>
 *
 * @author <a href="mailto:sjj@jianzhimao.com">mojo</a>
 * copyright (C), 2013-2021, 广州九尾信息科技有限公司
 * @date 2021/8/20 11:01
 */
public class CountdownLatchDemo1 {
    // 创建ThreadFactory
    static ThreadFactory tf = r -> new Thread(r);
    // 创建线程池
    public static ExecutorService pool = new ThreadPoolExecutor(8, 8, 60L,
            TimeUnit.SECONDS, new ArrayBlockingQueue<>(2000),
            tf,
            new ThreadPoolExecutor.CallerRunsPolicy());

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        // CountDownLatch signal = new CountDownLatch(5);
        // for (int i = 0; i < 50; i++) {
        //    new Thread(new CountdownLatchCounter(signal), "thread--" + i).start();
        //}
        ////3、等待指定数量线程执行完毕，继续主线程。。
        // signal.await();
        // System.out.println("主线程1===>" + Thread.currentThread().getName());

        /*CountDownLatch startSignal = new CountDownLatch(2);
        CountDownLatch doneSignal = new CountDownLatch(10);
        for (int i = 0; i < 100; i++) {
            new Thread(new CountdownLatchCounter(startSignal, doneSignal), "thread--" + i).start();
        }
        System.out.println("主线程1===>" + Thread.currentThread().getName());
        startSignal.countDown();
        System.out.println("主线程2===>" + Thread.currentThread().getName());
        doneSignal.await();
        System.out.println("主线程3===>" + Thread.currentThread().getName());*/

        // CompletableFuture
        int num = 50;
        // 0.创建闭锁对象
        CountDownLatch latch = new CountDownLatch(num);
        CountdownLatchCounter latchCounter = new CountdownLatchCounter(latch);
        Thread t = new Thread(latchCounter);
        // 1.执行拥有闭锁的线程
        List<CompletableFuture<Void>> futureList = new ArrayList<>();
        for (int i = 0; i < num; i++) {

            // CompletableFuture<Void> future = CompletableFuture.runAsync(t);
            // futureList.add(future);
            pool.execute(t);
        }
        // 2.闭锁await
        latch.await();
        System.out.println("主线程1===>" + Thread.currentThread().getName());
        // 2.对返回值做额外处理
        // for (CompletableFuture<Void> f : futureList) {
        //    System.out.println("future===>" + f.get());
        //}
        pool.shutdown();


    }

    /**
     * 闭锁
     */
    static class CountdownLatchCounter implements Runnable {
        private final CountDownLatch startSignal;
        private CountDownLatch doneSignal;

        public CountdownLatchCounter(CountDownLatch startSignal, CountDownLatch doneSignal) {
            this.startSignal = startSignal;
            this.doneSignal = doneSignal;
        }

        public CountdownLatchCounter(CountDownLatch startSignal) {
            this.startSignal = startSignal;
        }

        @Override
        public void run() {
            modeOne();
            // doTwo();

        }


        private void doTwo() {
            try {
                startSignal.await();
                doWork(new Random(100).nextLong());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                doneSignal.countDown();
            }
        }

        // 所有线程等待start,countDown方法state数值减少到0之前await一直等待
        // 类比Thread.join 方法，等指定数量的线程全部执行完
        private void modeOne() {
            // 1、线程实际处理业务
            long random = new Random().nextInt(200);
            try {
                Thread.sleep(random);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            doWork(random);
            // 2、递减锁存器的计数
            startSignal.countDown();
        }

        private void doWork(long random) {
            System.out.println("子线程名称:" + Thread.currentThread().getName() + ",随机数:" + random);
        }
    }
}
